home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python152_Src.lha / Python152_Source / Modules / amigamodule.c next >
C/C++ Source or Header  |  1999-04-26  |  28KB  |  1,273 lines

  1. /**************************************************************\
  2. **                                                            **
  3. **  AMIGA module implementation, for SAS/C version 6.58       **
  4. **                                                            **
  5. **  Made by Irmen de Jong (irmen@bigfoot.com)                 **
  6. **                                                            **
  7. **  27-mar-96: Added a lot of AmiTCP functions!               **
  8. **   2-apr-96: Many small fixes & enhancements.               **
  9. **  11-apr-96: Totally rewritten the environment handling.    **
  10. **             Now creates 4 separate dictionaries.           **
  11. **             Fixed link(), added symlink() and readlink().  **
  12. **  29-may-96: Added filenote() and fullpath()                **
  13. **  11-jun-96: Moved filenote() to doslib/SetComment          **
  14. **  12-jun-96: Removed execv                                  **
  15. **  29-Aug-96: fixed getcwd(), some minor errno fixes         **
  16. **  26-Dec-96: upgraded to 1.4: added putenv(), remove()      **
  17. **             fixed mkdir: default protbits (0777)           **
  18. **   6-Apr-97: fixed bug in readlink (lock was incorrect)     **
  19. **   6-Nov-97: added uname()                                  **
  20. **  12-Jan-98: upgraded to 1.5: fixed includes, new names,    **
  21. **             uses new Amiga/.../unixemul.c                  **
  22. **  28-Mar-98: fixed buffer overflow bug in convertenviron()  **
  23. **  27-Sep-98: added crc32 function                           **
  24. **  24-Dec-98: moved bunch of #defines to config.h            **
  25. **  25-Dec-98: added I-Net 225 support                        **
  26. **                                                            **
  27. **  Adapted from posixmodule.c; implements as much of the     **
  28. **  functionality of this module as possible.                 **
  29. **                                                            **
  30. **                                                            **
  31. **  TO DO: Implement execv(e) and threads (if possible).      **
  32. **                                                            **
  33. **  NOTE: Don't forget __io2errno conversion!!!!!!!!!!!!!!!!  **
  34. **                                                            **
  35. \**************************************************************/
  36.  
  37.  
  38. #include "Python.h"
  39. #include "osdefs.h"
  40.  
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <errno.h>
  44. #include <stat.h>
  45. #ifndef INET225
  46. #include <dos.h>
  47. #endif
  48. #include <proto/dos.h>
  49. #include <proto/exec.h>
  50. #include <dos/dosextens.h>
  51. #include <dos/var.h>
  52. #include <dos/dostags.h>
  53. #include <exec/execbase.h>
  54.  
  55. #include "mytime.h"     /* For clock_t on some systems */
  56.  
  57. #ifdef HAVE_UTIME_H
  58. #include <utime.h>
  59. #endif
  60.  
  61. #include <dirent.h>
  62. #define NAMLEN(dirent) strlen((dirent)->d_name)
  63.  
  64. #ifdef AMITCP
  65. #include <clib/netlib_protos.h>
  66. #endif
  67.  
  68. #ifdef INET225
  69. #include <proto/socket.h>
  70. static int _OSERR;
  71. #define getegid() getgid()
  72. #define geteuid() getuid()
  73. static __inline int dup(int oldsd) { return s_dup(oldsd); }
  74. static __inline int dup2(int oldsd, int newsd) { return s_dup2(oldsd, newsd); }
  75. #endif
  76.  
  77. #include "protos.h"
  78.  
  79. /* Return a dictionary corresponding to the AmigaDOS environment table. */
  80. /* That is, scan ENV: for global environment variables.                 */
  81. /* The local shell environment variables are put into another table.    */
  82.  
  83. static int
  84. convertenviron(PyObject **glob, PyObject **loc,
  85.                PyObject **both, PyObject **aliases)
  86. {
  87.     BPTR dlok;
  88.     struct FileInfoBlock __aligned fib;
  89.     PyObject *v;
  90.     char *dynbuf;
  91.     struct LocalVar *lvar;
  92.     struct List *localvars;
  93.  
  94.     *glob=PyDict_New();
  95.     *loc=PyDict_New();
  96.     *both=PyDict_New();
  97.     *aliases=PyDict_New();
  98.  
  99.     if(!*glob || !*loc || !*both || !*aliases)
  100.     {
  101.         if(*glob) Py_DECREF(*glob);
  102.         if(*loc) Py_DECREF(*loc);
  103.         if(*both) Py_DECREF(*both);
  104.         if(*aliases) Py_DECREF(*aliases);
  105.         return 0;
  106.     }
  107.  
  108.     /* Read global vars from ENV: */
  109.     /* Put them in 'glob' and in 'both'. */
  110.  
  111.     if(dlok=Lock("ENV:",ACCESS_READ))
  112.     {
  113.         if(Examine(dlok,&fib))
  114.         {
  115.             while(ExNext(dlok,&fib))
  116.             {
  117.                 if(fib.fib_DirEntryType<0)
  118.                 {
  119.                     if(dynbuf=malloc(fib.fib_Size+1))
  120.                     {
  121.                         int len=GetVar(fib.fib_FileName,dynbuf,fib.fib_Size+1,GVF_GLOBAL_ONLY);
  122.                         if(len>=0 && (v=PyString_FromString(dynbuf)))
  123.                         {
  124.                             PyDict_SetItemString(*glob,fib.fib_FileName,v);
  125.                             PyDict_SetItemString(*both,fib.fib_FileName,v);
  126.                             Py_DECREF(v);
  127.                         }
  128.                         free(dynbuf);
  129.                     }
  130.                 }
  131.             }
  132.         }
  133.     }
  134.  
  135.     if(dlok) UnLock(dlok);
  136.  
  137.     /* Scan the local shell environment, including "RC" and "Result2"!   */
  138.     /* Put shell vars in 'loc' and 'both', and aliases in 'aliases'. */
  139.     /* Because of the fact that the inserting of local vars into 'both' */
  140.     /* happens AFTER the insertion of global vars, the formor overwrite */
  141.     /* the latter, and thus have higher priority (as it should be). */
  142.  
  143.     localvars = (struct List*) &((struct Process*)FindTask(0))->pr_LocalVars;
  144.  
  145.     if(!IsListEmpty(localvars))
  146.     {
  147.         lvar = (struct LocalVar*) localvars->lh_Head;
  148.         do {
  149.             if(dynbuf=malloc(lvar->lv_Len+1))
  150.             {
  151.                 strncpy(dynbuf,lvar->lv_Value,lvar->lv_Len);
  152.                 dynbuf[lvar->lv_Len]=0;
  153.  
  154.                 if(v=PyString_FromString(dynbuf))
  155.                 {
  156.                     if(lvar->lv_Node.ln_Type==LV_VAR)
  157.                     {
  158.                         PyDict_SetItemString(*loc,lvar->lv_Node.ln_Name,v);
  159.                         PyDict_SetItemString(*both,lvar->lv_Node.ln_Name,v);
  160.                     }
  161.                     else if(lvar->lv_Node.ln_Type==LV_ALIAS)
  162.                         PyDict_SetItemString(*aliases,lvar->lv_Node.ln_Name,v);
  163.  
  164.                     Py_DECREF(v);
  165.                 }
  166.                 free(dynbuf);
  167.             }
  168.         } while((lvar=(struct LocalVar*)lvar->lv_Node.ln_Succ)->lv_Node.ln_Succ);
  169.     }
  170.  
  171.  
  172.     return 1;
  173. }
  174.  
  175.  
  176. static PyObject *AmigaError; /* Exception amiga.error */
  177.  
  178. /* Set a Amiga-specific error from errno, and return NULL */
  179.  
  180. static PyObject * amiga_error(void)
  181. {
  182.     return PyErr_SetFromErrno(AmigaError);
  183. }
  184.  
  185.  
  186. /* AMIGA generic methods */
  187.  
  188. static PyObject *
  189. amiga_1str(PyObject *args, int (*func)(const char *))
  190. {
  191.     char *path1;
  192.     int res;
  193.     if (!PyArg_Parse(args, "s", &path1))
  194.         return NULL;
  195.     Py_BEGIN_ALLOW_THREADS
  196.     res = (*func)(path1);
  197.     Py_END_ALLOW_THREADS
  198.     if (res < 0)
  199.         return amiga_error();
  200.     Py_INCREF(Py_None);
  201.     return Py_None;
  202. }
  203.  
  204. static PyObject *
  205. amiga_2str(PyObject *args, int (*func)(const char *, const char *))
  206. {
  207.     char *path1, *path2;
  208.     int res;
  209.     if (!PyArg_Parse(args, "(ss)", &path1, &path2))
  210.         return NULL;
  211.     Py_BEGIN_ALLOW_THREADS
  212.     res = (*func)(path1, path2);
  213.     Py_END_ALLOW_THREADS
  214.     if (res < 0)
  215.         return amiga_error();
  216.     Py_INCREF(Py_None);
  217.     return Py_None;
  218. }
  219.  
  220. static PyObject *
  221. amiga_strint(PyObject *args, int (*func)(const char *, int))
  222. {
  223.     char *path;
  224.     int i;
  225.     int res;
  226.     if (!PyArg_Parse(args, "(si)", &path, &i))
  227.         return NULL;
  228.     Py_BEGIN_ALLOW_THREADS
  229.     res = (*func)(path, i);
  230.     Py_END_ALLOW_THREADS
  231.     if (res < 0)
  232.         return amiga_error();
  233.     Py_INCREF(Py_None);
  234.     return Py_None;
  235. }
  236.  
  237. static PyObject *
  238. amiga_strintint(PyObject *args, int (*func)(const char *, int, int))
  239. {
  240.     char *path;
  241.     int i,i2;
  242.     int res;
  243.     if (!PyArg_Parse(args, "(sii)", &path, &i, &i2))
  244.         return NULL;
  245.     Py_BEGIN_ALLOW_THREADS
  246.     res = (*func)(path, i, i2);
  247.     Py_END_ALLOW_THREADS
  248.     if (res < 0)
  249.         return amiga_error();
  250.     Py_INCREF(Py_None);
  251.     return Py_None;
  252. }
  253.  
  254. static PyObject *
  255. amiga_do_stat(PyObject *self, PyObject *args, int (*statfunc)(const char *, struct stat *))
  256. {
  257.     struct stat st;
  258.     char *path;
  259.     int res;
  260.     if (!PyArg_Parse(args, "s", &path))
  261.         return NULL;
  262.     Py_BEGIN_ALLOW_THREADS
  263.     res = (*statfunc)(path, &st);
  264.     Py_END_ALLOW_THREADS
  265.     if (res != 0)
  266.         return amiga_error();
  267.     return Py_BuildValue("(llllllllll)",
  268.             (long)st.st_mode,
  269.             (long)st.st_ino,
  270.             (long)st.st_dev,
  271.             (long)st.st_nlink,
  272.             (long)st.st_uid,
  273.             (long)st.st_gid,
  274.             (long)st.st_size,
  275.             (long)st.st_atime,
  276.             (long)st.st_mtime,
  277.             (long)st.st_ctime);
  278. }
  279.  
  280.  
  281. /* AMIGA methods */
  282.  
  283. static PyObject *
  284. amiga_chdir(PyObject *self, PyObject *args)
  285. {
  286.     return amiga_1str(args, chdir);
  287. }
  288.  
  289. static PyObject *
  290. amiga_chmod(PyObject *self, PyObject *args)
  291. {
  292.     return amiga_strint(args, chmod);
  293. }
  294.  
  295. #ifdef HAVE_CHOWN
  296. static PyObject *
  297. amiga_chown(PyObject *self, PyObject *args)
  298. {
  299.     return amiga_strintint(args, chown);
  300. }
  301. #endif /* HAVE_CHOWN */
  302.  
  303. #ifdef HAVE_GETCWD
  304. static PyObject *
  305. amiga_getcwd(PyObject *self, PyObject *args)
  306. {
  307.     char buf[MAXPATHLEN];
  308.     char *res;
  309.     if (!PyArg_Parse(args,""))
  310.             return NULL;
  311.     Py_BEGIN_ALLOW_THREADS
  312.     res = getcwd(buf, sizeof buf);
  313.     Py_END_ALLOW_THREADS
  314.     if (res == NULL)
  315.             return amiga_error();
  316.     return PyString_FromString(buf);
  317. }
  318. #endif
  319.  
  320. #ifdef HAVE_LINK
  321. static PyObject *
  322. amiga_link(PyObject *self, PyObject *args)
  323. {
  324.     return amiga_2str(args, link);
  325. }
  326. #endif
  327.  
  328. static PyObject *
  329. amiga_listdir(PyObject *self, PyObject *args)
  330. {
  331.     BPTR dlok;
  332.     char *name;
  333.     struct FileInfoBlock __aligned fib;
  334.     PyObject *d;
  335.  
  336.     if (!PyArg_Parse(args, "s", &name)) return NULL;
  337.  
  338.     if ((d = PyList_New(0)) == NULL) return NULL;
  339.  
  340.     if(dlok=Lock(name,ACCESS_READ))
  341.     {
  342.         if(Examine(dlok,&fib))
  343.         {
  344.             while(ExNext(dlok,&fib))
  345.             {
  346.                 PyObject *v = PyString_FromString(fib.fib_FileName);
  347.                 if(v==NULL)
  348.                 {
  349.                     Py_DECREF(d); d=NULL; break;
  350.                 }
  351.  
  352.                 if(PyList_Append(d,v)!=0)
  353.                 {
  354.                     Py_DECREF(v); Py_DECREF(d); d=NULL; break;
  355.                 }
  356.                 Py_DECREF(v);
  357.             }
  358.         }
  359.         UnLock(dlok);
  360.     }
  361.  
  362.     if(IoErr()==ERROR_NO_MORE_ENTRIES) return d;
  363.  
  364.     Py_DECREF(d);
  365.     errno=__io2errno(_OSERR=IoErr());
  366.     return amiga_error();
  367. }
  368.  
  369. static PyObject *
  370. amiga_mkdir(PyObject *self, PyObject *args)
  371. {
  372.     int res;
  373.     char *path;
  374.     int mode = 0777;
  375.     if (!PyArg_ParseTuple(args, "s|i", &path, &mode)) return NULL;
  376.     Py_BEGIN_ALLOW_THREADS
  377. #ifdef INET225
  378.     res = mkdir(path, mode);
  379. #else
  380.     res = my_mkdir(path, mode);
  381. #endif
  382.     Py_END_ALLOW_THREADS
  383.     if (res < 0) return amiga_error();
  384.     Py_INCREF(Py_None); return Py_None;
  385. }
  386.  
  387. static PyObject *
  388. amiga_rename(PyObject *self, PyObject *args)
  389. {
  390.     return amiga_2str(args, rename);
  391. }
  392.  
  393. static PyObject *
  394. amiga_rmdir(PyObject *self, PyObject *args)
  395. {
  396.     return amiga_1str(args, rmdir);
  397. }
  398.  
  399. static PyObject *
  400. amiga_stat(PyObject *self, PyObject *args)
  401. {
  402.     return amiga_do_stat(self, args, stat);
  403. }
  404.  
  405. #ifdef HAVE_SYSTEM
  406. static PyObject *
  407. amiga_system(PyObject *self, PyObject *args)
  408. {
  409.     char *command;
  410.     long sts;
  411.     if (!PyArg_Parse(args, "s", &command))
  412.         return NULL;
  413.     Py_BEGIN_ALLOW_THREADS
  414.     sts = system(command);
  415.     Py_END_ALLOW_THREADS
  416.     return PyInt_FromLong(sts);
  417. }
  418. #endif
  419.  
  420. #if defined(AMITCP) || defined(INET225)
  421. static PyObject *
  422. amiga_umask(PyObject *self, PyObject *args)
  423. {
  424.     int i;
  425. #ifdef AMITCP
  426.     if (!checkusergrouplib()) return NULL;
  427. #else
  428.     if (!checksocketlib()) return NULL;
  429. #endif
  430.     if (!PyArg_Parse(args,"i",&i))
  431.         return NULL;
  432.     i = umask(i);
  433.     if (i < 0)
  434.         return amiga_error();
  435.     return PyInt_FromLong((long)i);
  436. }
  437. #endif
  438.  
  439. #ifdef HAVE_UNAME
  440. static PyObject *
  441. amiga_uname(PyObject *self, PyObject *args)
  442. {
  443.         struct utsname u;
  444.         int res;
  445.         if (!PyArg_NoArgs(args))
  446.                 return NULL;
  447.         Py_BEGIN_ALLOW_THREADS
  448.         res = uname(&u);
  449.         Py_END_ALLOW_THREADS
  450.         if (res < 0)
  451.                 return amiga_error();
  452.         return Py_BuildValue("(sssss)",
  453.                              u.sysname,
  454.                              u.nodename,
  455.                              u.release,
  456.                              u.version,
  457.                              u.machine);
  458. }
  459. #endif
  460.  
  461. static PyObject *
  462. amiga_unlink(PyObject *self, PyObject *args)
  463. {
  464.     return amiga_1str(args, unlink);
  465. }
  466.  
  467. #if defined(AMITCP) || defined(INET225)
  468. static PyObject *
  469. amiga_utime(PyObject *self, PyObject *args)
  470. {
  471.     char *path;
  472.     long atime, mtime;
  473.     int res;
  474.  
  475. #ifdef HAVE_UTIME_H
  476.     struct utimbuf buf;
  477. #define ATIME buf.actime
  478. #define MTIME buf.modtime
  479. #define UTIME_ARG &buf
  480. #else /* HAVE_UTIME_H */
  481.     time_t buf[2];
  482. #define ATIME buf[0]
  483. #define MTIME buf[1]
  484. #define UTIME_ARG buf
  485. #endif /* HAVE_UTIME_H */
  486.  
  487.     if (!PyArg_Parse(args, "(s(ll))", &path, &atime, &mtime))
  488.         return NULL;
  489.     ATIME = atime;
  490.     MTIME = mtime;
  491.     Py_BEGIN_ALLOW_THREADS
  492.     res = utime(path, UTIME_ARG);
  493.     Py_END_ALLOW_THREADS
  494.     if (res < 0)
  495.         return amiga_error();
  496.     Py_INCREF(Py_None);
  497.     return Py_None;
  498. #undef UTIME_ARG
  499. #undef ATIME
  500. #undef MTIME
  501. }
  502. #endif
  503.  
  504.  
  505. /* Process operations */
  506.  
  507. /* XXX Removed _exit. You are VERY STUPID if you used this. (2-apr-96) */
  508.  
  509. /* XXX Removed execv. You must use system/exit combination instead. */
  510. /*     Maybe one day I'll implement a REAL execv ?? */
  511.  
  512.  
  513.  
  514. #ifdef HAVE_GETEGID
  515. static PyObject *
  516. amiga_getegid(PyObject *self, PyObject *args)
  517. {
  518. #ifdef AMITCP
  519.     if (!checkusergrouplib()) return NULL;
  520. #else
  521.     if (!checksocketlib()) return NULL;
  522. #endif
  523.     if (!PyArg_Parse(args,""))
  524.         return NULL;
  525.     return PyInt_FromLong((long)getegid());
  526. }
  527. #endif
  528.  
  529. #ifdef HAVE_GETEUID
  530. static PyObject *
  531. amiga_geteuid(PyObject *self, PyObject *args)
  532. {
  533. #ifdef AMITCP
  534.     if (!checkusergrouplib()) return NULL;
  535. #else
  536.     if (!checksocketlib()) return NULL;
  537. #endif
  538.     if (!PyArg_Parse(args,""))
  539.         return NULL;
  540.     return PyInt_FromLong((long)geteuid());
  541. }
  542. #endif
  543.  
  544. #ifdef HAVE_GETGID
  545. static PyObject *
  546. amiga_getgid(PyObject *self, PyObject *args)
  547. {
  548. #ifdef AMITCP
  549.     if (!checkusergrouplib()) return NULL;
  550. #else
  551.     if (!checksocketlib()) return NULL;
  552. #endif
  553.     if (!PyArg_Parse(args,""))
  554.         return NULL;
  555.     return PyInt_FromLong((long)getgid());
  556. }
  557. #endif
  558.  
  559. static PyObject *
  560. amiga_getpid(PyObject *self, PyObject *args)
  561. {
  562.     if (!PyArg_Parse(args,""))
  563.         return NULL;
  564.     return PyInt_FromLong((long)FindTask(0));
  565. }
  566.  
  567. #ifdef HAVE_GETPGRP
  568. static PyObject *
  569. amiga_getpgrp(PyObject *self, PyObject *args)
  570. {
  571. #ifdef AMITCP
  572.     if (!checkusergrouplib()) return NULL;
  573. #else
  574.     if (!checksocketlib()) return NULL;
  575. #endif
  576.     if (!PyArg_Parse(args,""))
  577.         return NULL;
  578. #ifdef GETPGRP_HAVE_ARG
  579.     return PyInt_FromLong((long)getpgrp(0));
  580. #else /* GETPGRP_HAVE_ARG */
  581.     return PyInt_FromLong((long)getpgrp());
  582. #endif /* GETPGRP_HAVE_ARG */
  583. }
  584. #endif /* HAVE_GETPGRP */
  585.  
  586. #ifdef HAVE_SETPGRP
  587. static PyObject *
  588. amiga_setpgrp(PyObject *self, PyObject *args)
  589. {
  590. #ifdef AMITCP
  591.     if (!checkusergrouplib()) return NULL;
  592. #else
  593.     if (!checksocketlib()) return NULL;
  594. #endif
  595.     if (!PyArg_Parse(args,""))
  596.         return NULL;
  597. #ifdef SETPGRP_HAVE_ARG
  598.     if (setpgrp(0, 0) < 0)
  599. #else /* SETPGRP_HAVE_ARG */
  600.     if (setpgrp() < 0)
  601. #endif /* SETPGRP_HAVE_ARG */
  602.         return amiga_error();
  603.     Py_INCREF(Py_None);
  604.     return Py_None;
  605. }
  606.  
  607. #endif /* HAVE_SETPGRP */
  608.  
  609. #ifdef HAVE_GETPPID
  610. static PyObject *
  611. amiga_getppid(PyObject *self, PyObject *args)
  612. {
  613.     if (!PyArg_Parse(args,""))
  614.         return NULL;
  615.     return PyInt_FromLong((long)getppid());
  616. }
  617. #endif
  618.  
  619. #ifdef HAVE_GETUID
  620. static PyObject *
  621. amiga_getuid(PyObject *self, PyObject *args)
  622. {
  623. #ifdef AMITCP
  624.     if (!checkusergrouplib()) return NULL;
  625. #else
  626.     if (!checksocketlib()) return NULL;
  627. #endif
  628.     if (!PyArg_Parse(args,""))
  629.         return NULL;
  630.     return PyInt_FromLong((long)getuid());
  631. }
  632. #endif
  633.  
  634. #ifdef HAVE_POPEN
  635. static PyObject *
  636. amiga_popen(PyObject *self, PyObject *args)
  637. {
  638.     char *name;
  639.     char *mode = "r";
  640.     int bufsize = -1;
  641.     FILE *fp;
  642.     PyObject *f;
  643.     if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize))
  644.         return NULL;
  645.     Py_BEGIN_ALLOW_THREADS
  646.     fp = popen(name, mode);
  647.     Py_END_ALLOW_THREADS
  648.     if (fp == NULL)
  649.         return amiga_error();
  650.     f = PyFile_FromFile(fp, name, mode, pclose);
  651.     if (f != NULL)
  652.         PyFile_SetBufSize(f, bufsize);
  653.     return f;
  654. }
  655. #endif
  656.  
  657. #ifdef HAVE_SETUID
  658. static PyObject *
  659. amiga_setuid(PyObject *self, PyObject *args)
  660. {
  661.     int uid;
  662. #ifdef AMITCP
  663.     if (!checkusergrouplib()) return NULL;
  664. #else
  665.     if (!checksocketlib()) return NULL;
  666. #endif
  667.     if (!PyArg_Parse(args, "i", &uid))
  668.         return NULL;
  669.     if (setuid(uid) < 0)
  670.         return amiga_error();
  671.     Py_INCREF(Py_None);
  672.     return Py_None;
  673. }
  674. #endif /* HAVE_SETUID */
  675.  
  676. #ifdef HAVE_SETGID
  677. static PyObject *
  678. amiga_setgid(PyObject *self, PyObject *args)
  679. {
  680.     int gid;
  681. #ifdef AMITCP
  682.     if (!checkusergrouplib()) return NULL;
  683. #else
  684.     if (!checksocketlib()) return NULL;
  685. #endif
  686.     if (!PyArg_Parse(args, "i", &gid))
  687.         return NULL;
  688.     if (setgid(gid) < 0)
  689.         return amiga_error();
  690.     Py_INCREF(Py_None);
  691.     return Py_None;
  692. }
  693. #endif /* HAVE_SETGID */
  694.  
  695. static PyObject *
  696. amiga_lstat(PyObject *self, PyObject *args)
  697. {
  698. #ifdef HAVE_LSTAT
  699.     return amiga_do_stat(self, args, lstat);
  700. #else /* !HAVE_LSTAT */
  701.     return amiga_do_stat(self, args, stat);
  702. #endif /* !HAVE_LSTAT */
  703. }
  704.  
  705. #ifdef HAVE_READLINK
  706. static PyObject *
  707. amiga_readlink(PyObject *self, PyObject *args)
  708. {
  709.     char buf[MAXPATHLEN];
  710.     char *path;
  711.     int n;
  712.     if (!PyArg_Parse(args, "s", &path))
  713.             return NULL;
  714.     Py_BEGIN_ALLOW_THREADS
  715.     n = readlink(path, buf, (int) sizeof buf);
  716.     Py_END_ALLOW_THREADS
  717.     if (n < 0)
  718.             return amiga_error();
  719.     return PyString_FromStringAndSize(buf, n);
  720. }
  721. #endif
  722.  
  723. #ifdef HAVE_SYMLINK
  724. static PyObject *
  725. amiga_symlink(PyObject *self, PyObject *args)
  726. {
  727.     return amiga_2str(args, symlink);
  728. }
  729. #endif
  730.  
  731. #ifdef HAVE_SETSID
  732. static PyObject *
  733. amiga_setsid(PyObject *self, PyObject *args)
  734. {
  735. #ifdef AMITCP
  736.     if (!checkusergrouplib()) return NULL;
  737. #else
  738.     if (!checksocketlib()) return NULL;
  739. #endif
  740.     if (!PyArg_Parse(args,""))
  741.         return NULL;
  742.     if ((int)setsid() < 0)
  743.         return amiga_error();
  744.     Py_INCREF(Py_None);
  745.     return Py_None;
  746. }
  747. #endif /* HAVE_SETSID */
  748.  
  749. #ifdef HAVE_SETPGID
  750. static PyObject *
  751. amiga_setpgid(PyObject *self, PyObject *args)
  752. {
  753.     int pid, pgrp;
  754.     if (!PyArg_Parse(args, "(ii)", &pid, &pgrp))
  755.         return NULL;
  756.     if (setpgid(pid, pgrp) < 0)
  757.         return amiga_error();
  758.     Py_INCREF(Py_None);
  759.     return Py_None;
  760. }
  761. #endif /* HAVE_SETPGID */
  762.  
  763. /* Functions acting on file descriptors */
  764.  
  765. static PyObject *
  766. amiga_open(PyObject *self, PyObject *args)
  767. {
  768.     char *file;
  769.     int flag;
  770.     int mode = 0777;
  771.     int fd;
  772.     if (!PyArg_Parse(args, "(si)", &file, &flag)) {
  773.         PyErr_Clear();
  774.         if (!PyArg_Parse(args, "(sii)", &file, &flag, &mode))
  775.             return NULL;
  776.     }
  777.     Py_BEGIN_ALLOW_THREADS
  778.     fd = open(file, flag, mode);
  779.     Py_END_ALLOW_THREADS
  780.     if (fd < 0)
  781.         return amiga_error();
  782.     return PyInt_FromLong((long)fd);
  783. }
  784.  
  785. static PyObject *
  786. amiga_close(PyObject *self, PyObject *args)
  787. {
  788.     int fd, res;
  789.     if (!PyArg_Parse(args, "i", &fd))
  790.         return NULL;
  791.     Py_BEGIN_ALLOW_THREADS
  792.     res = close(fd);
  793.     Py_END_ALLOW_THREADS
  794.     if (res < 0)
  795.         return amiga_error();
  796.     Py_INCREF(Py_None);
  797.     return Py_None;
  798. }
  799.  
  800. #if defined(AMITCP) || defined(INET225)
  801. static PyObject *
  802. amiga_dup(PyObject *self, PyObject *args)
  803. {
  804.     int fd;
  805.     if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
  806.     if (!PyArg_Parse(args, "i", &fd))
  807.         return NULL;
  808.     Py_BEGIN_ALLOW_THREADS
  809.     fd = dup(fd);
  810.     Py_END_ALLOW_THREADS
  811.     if (fd < 0)
  812.         return amiga_error();
  813.     return PyInt_FromLong((long)fd);
  814. }
  815.  
  816. static PyObject *
  817. amiga_dup2(PyObject *self, PyObject *args)
  818. {
  819.     int fd, fd2, res;
  820.     if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
  821.     if (!PyArg_Parse(args, "(ii)", &fd, &fd2))
  822.         return NULL;
  823.     Py_BEGIN_ALLOW_THREADS
  824.     res = dup2(fd, fd2);
  825.     Py_END_ALLOW_THREADS
  826.     if (res < 0)
  827.         return amiga_error();
  828.     Py_INCREF(Py_None);
  829.     return Py_None;
  830. }
  831. #endif
  832.  
  833. static PyObject *
  834. amiga_lseek(PyObject *self, PyObject *args)
  835. {
  836.     int fd, how;
  837.     long pos, res;
  838.     if (!PyArg_Parse(args, "(ili)", &fd, &pos, &how))
  839.         return NULL;
  840. #ifdef SEEK_SET
  841.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  842.     switch (how) {
  843.     case 0: how = SEEK_SET; break;
  844.     case 1: how = SEEK_CUR; break;
  845.     case 2: how = SEEK_END; break;
  846.     }
  847. #endif /* SEEK_END */
  848.     Py_BEGIN_ALLOW_THREADS
  849.     res = lseek(fd, pos, how);
  850.     Py_END_ALLOW_THREADS
  851.     if (res < 0)
  852.         return amiga_error();
  853.     return PyInt_FromLong(res);
  854. }
  855.  
  856. static PyObject *
  857. amiga_read(PyObject *self, PyObject *args)
  858. {
  859.     int fd, size;
  860.     PyObject *buffer;
  861.     if (!PyArg_Parse(args, "(ii)", &fd, &size))
  862.         return NULL;
  863.     buffer = PyString_FromStringAndSize((char *)NULL, size);
  864.     if (buffer == NULL)
  865.         return NULL;
  866.     Py_BEGIN_ALLOW_THREADS
  867.     size = read(fd, PyString_AsString(buffer), size);
  868.     Py_END_ALLOW_THREADS
  869.     if (size < 0) {
  870.         Py_DECREF(buffer);
  871.         return amiga_error();
  872.     }
  873.     _PyString_Resize(&buffer, size);
  874.     return buffer;
  875. }
  876.  
  877. static PyObject *
  878. amiga_write(PyObject *self, PyObject *args)
  879. {
  880.     int fd, size;
  881.     char *buffer;
  882.     if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
  883.         return NULL;
  884.     Py_BEGIN_ALLOW_THREADS
  885.     size = write(fd, buffer, size);
  886.     Py_END_ALLOW_THREADS
  887.     if (size < 0)
  888.         return amiga_error();
  889.     return PyInt_FromLong((long)size);
  890. }
  891.  
  892. static PyObject *
  893. amiga_fstat(PyObject *self, PyObject *args)
  894. {
  895.     int fd;
  896.     struct stat st;
  897.     int res;
  898.     if (!PyArg_Parse(args, "i", &fd))
  899.         return NULL;
  900.     Py_BEGIN_ALLOW_THREADS
  901.     res = fstat(fd, &st);
  902.     Py_END_ALLOW_THREADS
  903.     if (res != 0)
  904.         return amiga_error();
  905.     return Py_BuildValue("(llllllllll)",
  906.             (long)st.st_mode,
  907.             (long)st.st_ino,
  908.             (long)st.st_dev,
  909.             (long)st.st_nlink,
  910.             (long)st.st_uid,
  911.             (long)st.st_gid,
  912.             (long)st.st_size,
  913.             (long)st.st_atime,
  914.             (long)st.st_mtime,
  915.             (long)st.st_ctime);
  916. }
  917.  
  918. static PyObject *
  919. amiga_fdopen(PyObject *self, PyObject *args)
  920. {
  921.     int fd;
  922.     char *mode = "r";
  923.     int bufsize = -1;
  924.     FILE *fp;
  925.     PyObject *f;
  926.     if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize))
  927.         return NULL;
  928.     Py_BEGIN_ALLOW_THREADS
  929.     fp = fdopen(fd, mode);
  930.     Py_END_ALLOW_THREADS
  931.     if (fp == NULL)
  932.         return amiga_error();
  933.     f = PyFile_FromFile(fp, "(fdopen)", mode, fclose);
  934.     if (f != NULL)
  935.         PyFile_SetBufSize(f, bufsize);
  936.     return f;
  937. }
  938.  
  939. #if 0
  940. /*** XXX pipe() is useless without fork() or threads ***/
  941. /***     TODO: guess what.. implement threads! ***/
  942. static int pipe(int *fildes)
  943. {
  944.     /* 0=ok, -1=err, errno=EMFILE,ENFILE,EFAULT */
  945.     char buf[50];
  946.     static int num = 1;
  947.     
  948.     sprintf(buf,"PIPE:Py%ld_%ld",FindTask(0),num++);
  949.     fildes[0]=open(buf,O_RDONLY,0);
  950.     if(fildes[0]>0)
  951.     {
  952.         fildes[1]=open(buf,O_WRONLY|O_CREAT,FIBF_OTR_READ|FIBF_OTR_WRITE);
  953.         if(fildes[1]>0)
  954.         {
  955.             return 0;
  956.         }
  957.         close(fildes[0]);
  958.     }
  959.     return -1;
  960. }
  961.  
  962. static PyObject *
  963. amiga_pipe(PyObject *self, PyObject *args)
  964. {
  965.     int fds[2];
  966.     int res;
  967.     if (!PyArg_Parse(args, ""))
  968.         return NULL;
  969.     Py_BEGIN_ALLOW_THREADS
  970.     res = pipe(fds);
  971.     Py_END_ALLOW_THREADS
  972.     if (res != 0)
  973.         return amiga_error();
  974.     return Py_BuildValue("(ii)", fds[0], fds[1]);
  975. }
  976. #endif
  977.  
  978.  
  979. static PyObject *
  980. amiga_fullpath(PyObject *self, PyObject *args)
  981. {
  982.     BOOL ok=FALSE;
  983.     BPTR lk;
  984.     char *path;
  985.     char buf[MAXPATHLEN];
  986.  
  987.     if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
  988.  
  989.     Py_BEGIN_ALLOW_THREADS
  990.     if(lk=Lock(path,SHARED_LOCK))
  991.     {
  992.         ok=NameFromLock(lk,buf,sizeof(buf));
  993.         UnLock(lk);
  994.     }
  995.     Py_END_ALLOW_THREADS
  996.  
  997.     if(!ok)
  998.     {
  999.         errno=__io2errno(_OSERR=IoErr());
  1000.         return amiga_error();
  1001.     }
  1002.     else return PyString_FromString(buf);
  1003. }
  1004.  
  1005. static PyObject *amiga_putenv(PyObject *self, PyObject *args)
  1006. {
  1007.     char *s1, *s2;
  1008.  
  1009.     if (!PyArg_ParseTuple(args, "ss", &s1, &s2)) return NULL;
  1010.     if(setenv(s1,s2,1))
  1011.     {
  1012.         amiga_error(); return NULL;
  1013.     }
  1014.     
  1015.     Py_INCREF(Py_None); return Py_None;
  1016. }
  1017.  
  1018. #ifdef HAVE_STRERROR
  1019. static char posix_strerror__doc__[] =
  1020. "strerror(code) -> string\n\
  1021. Translate an error code to a message string.";
  1022.  
  1023. PyObject *
  1024. amiga_strerror(PyObject *self, PyObject *args)
  1025. {
  1026.     int code;
  1027.     char *message;
  1028.     if (!PyArg_ParseTuple(args, "i", &code))
  1029.         return NULL;
  1030.     message = strerror(code);
  1031.     if (message == NULL) {
  1032.         PyErr_SetString(PyExc_ValueError,
  1033.                 "strerror code out of range");
  1034.         return NULL;
  1035.     }
  1036.     return PyString_FromString(message);
  1037. }
  1038. #endif /* strerror */
  1039.  
  1040. // external function prototype:
  1041. unsigned long __asm CalcCRC32(register __a1 const void *data, register __d1 unsigned long size);
  1042.  
  1043. PyObject *
  1044. amiga_crc32(PyObject *self, PyObject *args)
  1045. {
  1046.     PyObject *py_str;
  1047.     if(!PyArg_ParseTuple(args,"S",&py_str)) return NULL;
  1048.     return PyInt_FromLong(CalcCRC32(PyString_AsString(py_str), PyString_Size(py_str)));
  1049. }
  1050.  
  1051.  
  1052. static struct PyMethodDef amiga_methods[] = {
  1053.     {"chdir",   amiga_chdir},
  1054.     {"chmod",   amiga_chmod},
  1055. #ifdef HAVE_CHOWN
  1056.     {"chown",   amiga_chown},
  1057. #endif
  1058. #ifdef HAVE_GETCWD
  1059.     {"getcwd",  amiga_getcwd},
  1060. #endif
  1061.     {"fullpath", amiga_fullpath,1},
  1062. #ifdef HAVE_LINK
  1063.     {"link",    amiga_link},
  1064. #endif
  1065.     {"listdir", amiga_listdir},
  1066.     {"lstat",   amiga_lstat},
  1067.     {"mkdir",   amiga_mkdir , 1},
  1068. #ifdef HAVE_READLINK
  1069.     {"readlink",    amiga_readlink},
  1070. #endif
  1071.     {"rename",  amiga_rename},
  1072.     {"rmdir",   amiga_rmdir},
  1073.     {"stat",    amiga_stat},
  1074. #ifdef HAVE_SYMLINK
  1075.     {"symlink", amiga_symlink},
  1076. #endif
  1077. #ifdef HAVE_SYSTEM
  1078.     {"system",  amiga_system},
  1079. #endif
  1080. #if defined(AMITCP) || defined(INET225)
  1081.     {"umask",   amiga_umask},
  1082. #endif
  1083. #ifdef HAVE_UNAME
  1084.     {"uname",   amiga_uname},
  1085. #endif
  1086.     {"unlink",  amiga_unlink},
  1087.     {"remove",  amiga_unlink},
  1088. #if defined(AMITCP) || defined(INET225)
  1089.     {"utime",   amiga_utime},
  1090. #endif
  1091. #ifdef HAVE_TIMES
  1092.     {"times",   amiga_times},
  1093. #endif
  1094. #ifdef HAVE_EXECV
  1095.     {"execv",    amiga_execv},
  1096.     {"execve",    amiga_execve},
  1097. #endif /* HAVE_EXECV */
  1098. #ifdef HAVE_GETEGID
  1099.     {"getegid", amiga_getegid},
  1100. #endif
  1101. #ifdef HAVE_GETEUID
  1102.     {"geteuid", amiga_geteuid},
  1103. #endif
  1104. #ifdef HAVE_GETGID
  1105.     {"getgid",  amiga_getgid},
  1106. #endif
  1107.     {"getpid",  amiga_getpid},
  1108. #ifdef HAVE_GETPGRP
  1109.     {"getpgrp", amiga_getpgrp},
  1110. #endif
  1111. #ifdef HAVE_GETPPID
  1112.     {"getppid", amiga_getppid},
  1113. #endif
  1114. #ifdef HAVE_GETUID
  1115.     {"getuid",  amiga_getuid},
  1116. #endif
  1117. #ifdef HAVE_POPEN
  1118.     {"popen",   amiga_popen,    1},
  1119. #endif
  1120. #ifdef HAVE_SETUID
  1121.     {"setuid",  amiga_setuid},
  1122. #endif
  1123. #ifdef HAVE_SETGID
  1124.     {"setgid",  amiga_setgid},
  1125. #endif
  1126. #ifdef HAVE_SETPGRP
  1127.     {"setpgrp", amiga_setpgrp},
  1128. #endif
  1129. #ifdef HAVE_SETSID
  1130.     {"setsid",  amiga_setsid},
  1131. #endif
  1132. #ifdef HAVE_SETPGID
  1133.     {"setpgid", amiga_setpgid},
  1134. #endif
  1135. #ifdef HAVE_TCGETPGRP
  1136.     {"tcgetpgrp",   amiga_tcgetpgrp},
  1137. #endif
  1138. #ifdef HAVE_TCSETPGRP
  1139.     {"tcsetpgrp",   amiga_tcsetpgrp},
  1140. #endif
  1141.     {"open",    amiga_open},
  1142.     {"close",   amiga_close},
  1143. #if defined(AMITCP) || defined(INET225)
  1144.     {"dup",     amiga_dup},
  1145.     {"dup2",    amiga_dup2},
  1146. #endif
  1147.     {"lseek",   amiga_lseek},
  1148.     {"read",    amiga_read},
  1149.     {"write",   amiga_write},
  1150.     {"fstat",   amiga_fstat},
  1151.     {"fdopen",  amiga_fdopen,   1},
  1152. #ifdef HAVE_MKFIFO
  1153.     {"mkfifo",    amiga_mkfifo, 1},
  1154. #endif
  1155. #ifdef HAVE_FTRUNCATE
  1156.     {"ftruncate",    amiga_ftruncate, 1},
  1157. #endif
  1158. #ifdef HAVE_PUTENV
  1159.     {"putenv", amiga_putenv, 1},
  1160. #endif
  1161. #ifdef HAVE_STRERROR
  1162.     {"strerror",    amiga_strerror, 1},
  1163. #endif
  1164. #if 0
  1165.     /* XXX TODO: implement threads. Otherwise pipe() is useless. */
  1166.     {"pipe",    amiga_pipe},
  1167. #endif
  1168.     {"crc32",    amiga_crc32, 1},
  1169.     {NULL,      NULL}        /* Sentinel */
  1170. };
  1171.  
  1172.  
  1173. static int
  1174. ins(PyObject *d, char *symbol, long value)
  1175. {
  1176.         PyObject* v = PyInt_FromLong(value);
  1177.         if (!v || PyDict_SetItemString(d, symbol, v) < 0)
  1178.                 return -1;                   /* triggers fatal error */
  1179.  
  1180.         Py_DECREF(v);
  1181.         return 0;
  1182. }
  1183.  
  1184. static int all_ins(PyObject *d)
  1185. {
  1186. #ifdef WNOHANG
  1187.         if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
  1188. #endif        
  1189. #ifdef O_RDONLY
  1190.         if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
  1191. #endif
  1192. #ifdef O_WRONLY
  1193.         if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
  1194. #endif
  1195. #ifdef O_RDWR
  1196.         if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
  1197. #endif
  1198. #ifdef O_NDELAY
  1199.         if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
  1200. #endif
  1201. #ifdef O_NONBLOCK
  1202.         if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
  1203. #endif
  1204. #ifdef O_APPEND
  1205.         if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
  1206. #endif
  1207. #ifdef O_DSYNC
  1208.         if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
  1209. #endif
  1210. #ifdef O_RSYNC
  1211.         if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
  1212. #endif
  1213. #ifdef O_SYNC
  1214.         if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
  1215. #endif
  1216. #ifdef O_NOCTTY
  1217.         if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
  1218. #endif
  1219. #ifdef O_CREAT
  1220.         if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
  1221. #endif
  1222. #ifdef O_EXCL
  1223.         if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
  1224. #endif
  1225. #ifdef O_TRUNC
  1226.         if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
  1227. #endif
  1228. #ifdef O_BINARY
  1229.         if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
  1230. #endif
  1231. #ifdef O_TEXT
  1232.         if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
  1233. #endif
  1234.  
  1235. #if defined(PYOS_OS2)
  1236.         if (insertvalues(d)) return -1;
  1237. #endif
  1238.         return 0;
  1239. }
  1240.  
  1241. void
  1242. initamiga(void)
  1243. {
  1244.     PyObject *m, *d, *globv, *locv, *bothv, *aliases;
  1245.  
  1246.     m = Py_InitModule("amiga", amiga_methods);
  1247.     d = PyModule_GetDict(m);
  1248.     
  1249.     /* Initialize amiga.environ dictionary */
  1250.     if(!convertenviron(&globv, &locv, &bothv, &aliases))
  1251.         Py_FatalError("can't read environment");
  1252.  
  1253.     if (PyDict_SetItemString(d, "environ", bothv) != 0)
  1254.         Py_FatalError("can't define amiga.environ");
  1255.     Py_DECREF(bothv);
  1256.     if (PyDict_SetItemString(d, "globalvars", globv) != 0)
  1257.         Py_FatalError("can't define amiga.globalvars");
  1258.     Py_DECREF(globv);
  1259.     if (PyDict_SetItemString(d, "shellvars", locv) != 0)
  1260.         Py_FatalError("can't define amiga.shellvars");
  1261.     Py_DECREF(locv);
  1262.     if (PyDict_SetItemString(d, "shellaliases", aliases ) != 0)
  1263.         Py_FatalError("can't define amiga.shellaliases");
  1264.     Py_DECREF(aliases);
  1265.  
  1266.     if(all_ins(d)) return;
  1267.  
  1268.     /* Initialize exception */
  1269.     AmigaError = PyErr_NewException("os.error", NULL, NULL);
  1270.     if (AmigaError != NULL)
  1271.         PyDict_SetItemString(d, "error", AmigaError);
  1272. }
  1273.